package com.atguigu.service;

import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.data.message.ChatMessage;
import dev.langchain4j.data.message.SystemMessage;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.model.chat.response.ChatResponse;
import dev.langchain4j.model.openai.OpenAiChatModel;

import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Properties;

public class ChatService {
    private static OpenAiChatModel chatModel;
    private static ArrayList<ChatMessage> chatMessages = new ArrayList<>();//聊天记录
    private static ArrayList<ChatMessage> summaryMessages = new ArrayList<>();//摘要
    private static final int MAX_COUNT = 10;//每次请求的数量，每MAX_COUNT次聊天，生成一个摘要
    private static String title;//标题
    private static String messageDir;
    /*
    摘要：提取前面的聊天记录的关键信息，汇总成一条摘要。chatMessages里面有10条记录，就生成一个摘要。
    摘要仍然让AI帮我们生成。
     */
    static {
        try {
            //静态代码块
            Properties properties = new Properties();
            ClassLoader classLoader = ChatService.class.getClassLoader();
            properties.load(classLoader.getResourceAsStream("ai.properties"));
            String apiKeyName = properties.getProperty("apiKeyName");
            String apiKey = System.getenv(apiKeyName);
            String baseUrl = properties.getProperty("baseUrl");
            String modelName = properties.getProperty("modelName");
            messageDir = properties.getProperty("messageDir");

            chatModel = OpenAiChatModel.builder()
                    .apiKey(apiKey)
                    .baseUrl(baseUrl)
                    .modelName(modelName)
                    .build();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //处理用户提问
    public static String chat(String question) throws IOException {
        //设置标题
        //第一个问题的前10个字通常可以作为文件标题
        if(title==null){
            String str = question;
            str = str.replaceAll("[^\\u4e00-\\u9fffa-zA-Z0-9]","");//正则表达式，将所有非常用字符替换为空
            if(str.length()>10){//判断长度，如果超过10，就截取10个字，否则，直接输出
                str = str.substring(0,10);
            }
            title = str + ".txt";
        }

        if(chatMessages.size() >= MAX_COUNT){//这里考虑如果达到生成摘要临界的情况
            //这段代码是对自动生成摘要的代码
            SystemMessage systemMessage = SystemMessage.from("你是一个小助手，帮我整理一下这些聊天记录的摘要");
            ArrayList<ChatMessage> list = new ArrayList<>();//创建一个类型为ChatMessage的list集合
            list.add(systemMessage);
            list.addAll(chatMessages);//把之前的聊天记录存进去
            list.addAll(summaryMessages);//把之前的摘要也存进去

            ChatResponse chatResponse = chatModel.chat(list);//这是对
            AiMessage aiMessage = chatResponse.aiMessage();
            summaryMessages.add(aiMessage);

            //存储聊天记录
            saveChatRecords();
            //chatMessages集合中的聊天记录已经生成摘要，可以从chatMessages里面删除了
            chatMessages.clear();
        }

        UserMessage userMessage = UserMessage.from(question);
        chatMessages.add(userMessage);//添加本次用户问题

        ArrayList<ChatMessage> list = new ArrayList<>();
        list.addAll(chatMessages);//用户问题 + AI回答
        list.addAll(summaryMessages);//纯摘要
        //本次聊天发送给AI有（1）最近的10条之内的聊天记录（2）之前旧聊天记录的摘要
        ChatResponse chatResponse = chatModel.chat(list);//发送整个集合
        AiMessage aiMessage = chatResponse.aiMessage();
        chatMessages.add(aiMessage);//添加AI回答
        return aiMessage.text();
    }

    public static void saveChatRecords() throws FileNotFoundException {
        FileOutputStream fos = new FileOutputStream(messageDir + "\\" + title,true);
        PrintStream ps = new PrintStream(fos);
        for (ChatMessage chatMessage : chatMessages) {
            if(chatMessage instanceof UserMessage u){
                ps.println("我：" + u.singleText());
            }else if(chatMessage instanceof AiMessage a){
                ps.println("AI：" + a.text() );
            }
        }
    }

    public static ArrayList<File> listAllHistories(){
        File dir = new File(messageDir);
        File[] files = dir.listFiles();
        ArrayList<File> allFiles = new ArrayList<>();
        Collections.addAll(allFiles, files);
       return allFiles;
    }
}
